
class User
  include DataMapper::Resource
  property :id, Serial
  property :name, String
  property :nick, String
  property :email, String
  property :registered, Time
  property :secret, String

  def save
    @secret ||= '123456789123456789123456789'
    super
  end

  RANKS = {
    (1..2) => 'zelenáč',
    (3..4) => 'bažant',
    (5..6) => 'nadějný',
    (7..8) => 'pokročilý',
    (9..10) => 'hacker',
    (11..12) => 'mistr tříska',
    (13..14) => 'Bob Martin',
    (15..16) => 'Kent Beck',
    (17..18) => 'Alan Kay',
    (19..20) => 'Alan Turing'
  }


  def experience_for level
    if level == 1
      0
    else
      500*(2**(level - 2))
    end
  end

  def nick
    @nick || @name
  end

  def rank
    RANKS.select { |k, v| k.include?(level) }.first[1]
  end

  def level
    if !@level
      attribute_set(:level, 1)
    end
    @level
  end

  def experience
    if !@experience
      attribute_set(:experience, 0)
    end
    @experience
  end

  def self.for appengine_user
    if appengine_user
      first(:email => appengine_user.email) || create_for(appengine_user)
    else
      nil
    end
  end

  def programs o = {}
    Program.all(o.merge :author => self)
  end

  def progress
    this_level = experience_for(level)
    next_level = experience_for(level+1)
    exp_difference = next_level - this_level
    (experience - this_level)*1.0 / exp_difference
  end

  def save
    super || (raise "could not save #{self.inspect}.")
  end

  def solved_problems
    if !@solved_problems
      if problems = attribute_get(:solved_problems)
        @solved_problems = JSON.parse(problems)
      else
        @solved_problems = []
      end
    else
      @solved_problems
    end
  end

  def problems_solved
    solved_problems.length
  end

  def save
    if solved_problems.is_a? Array
      self.solved_problems = solved_problems.to_json
    end
    super
  end

  def self.create_for appengine_user
    user = new(:email => appengine_user.email)
    user.name = appengine_user.nickname.split('@').first
    user.registered = Time.now
    user.save
    user
  end

  class Test < AppTest
    def test_solved_problems_is_an_array_by_default
      u = User.new
      eq u.solved_problems, []
    end

    def test_solved_problems_can_be_added
      u = User.new
      u.solved_problems << 123
      eq u.solved_problems, [123]
    end
  end
end
